package com.xcity.game.combat;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.game.combat.attr.CombatAttributeType;
import com.xcity.game.combat.unit.CombatUnit;
import com.xcity.game.combat.unit.UnitAttribute;

/**
 * 一次战斗行动产生的效果
 * @author yang.li
 *
 */
public class ActionEffect {

	protected Action ref;
	protected byte result;
	protected CombatUnit unit; // 受影响的单位
//	public int hpDelta, mpDelta; // hp, mp变化值
//	private int hp, mp;
//	private List<CombatBuff> buffs;
	protected List<Value> values; // 影响值
	
	public static final byte RESULT_FAIL = 0; // 攻击失败
	public static final byte RESULT_HIT = 1; // 命中
	public static final byte RESULT_CRIT = 2; // 暴击
	public static final byte RESULT_MISS = 3; // miss
	public static final byte RESULT_IMMUNE = 4; // 免疫
	
	public static class Value extends UnitAttribute {
		protected int delta; // 变化值
		protected float realDelta; // 实际伤害/治疗量
		protected Value(CombatAttributeType type, int delta, int value) {
			super(type, value);
			this.delta = delta;
		}
		public int getDelta() {
			return delta;
		}
		public void setDelta(int delta) {
			this.delta = delta;
		}
	}
	
	public ActionEffect(Action ref, CombatUnit unit) {
		this.ref = ref;
		this.unit = unit;
	}
	
	@JSONField(serialize = false)
	public CombatUnit getUnit() {
		return unit;
	}
	
	public void setUnit(CombatUnit unit) {
		this.unit = unit;
	}
	
	@JSONField(serialize = false)
	public boolean isHit() {
		return result == RESULT_HIT || result == RESULT_CRIT;
	}
	
	public synchronized void rollback() {
//		int val = -hpDelta;
//		if (val > 0) {
//			unit.addHp(val);
//		} else {
//			unit.decHp(val);
//		}
//		val = -mpDelta;
//		if (val > 0) {
//			unit.addMp(val);
//		} else {
//			unit.decMp(val);
//		}
		for (int i = values != null ? values.size() - 1 : -1; i >= 0; i--) {
			Value v = values.get(i);
			if (v.realDelta != 0) {
				float delta = -v.realDelta;
				float oldVal = unit.getAttributeValue(v.getType());
				unit.setAttributeValue(v.getType(), oldVal + delta);
			}
		}
	}
	
	public void effect(CombatAttributeType type, int delta) {
		Value v = addValue(type, delta, 0);
		if (type == CombatAttributeType.HP && delta < 0) {
			unit.preDamage(this); // 修正伤害
			ref.unit.preDamage0(this);
		}
		delta = v.delta;
		float oldVal = unit.getAttributeValue(type);
		float val = unit.setAttributeValue(type, oldVal + delta);
		v.setValue(val);
		v.realDelta = val - oldVal; // 实际伤害/治疗量
		if (type == CombatAttributeType.HP) {
			unit.afterDamage(this);
			ref.unit.afterDamage0(this);
		} else {
			addValue(CombatAttributeType.HP, 0, unit.getHp());
		}
//		if (type == CombatAttributeType.HP) {
//			hpDelta = delta;
//			if (delta < 0) {
//				unit.preDamage(this); // buff修正伤害
//			}
//			int _hp = hpDelta > 0 ? unit.addHp(hpDelta) : unit.decHp(-hpDelta);
//			hp = _hp;
//		} else if (type == CombatAttributeType.MP) {
//			int _mp = delta > 0 ? unit.addMp(delta) : unit.decHp(-delta);
//			mpDelta = delta;
//			mp = _mp;
//			hp = unit.getHp();
//		}
	}
	
	public Value getValue(CombatAttributeType type) {
		if (values == null) {
			return null;
		}
		for (int i = values.size() - 1; i >= 0; i--) {
			Value v = values.get(i);
			if (v.getType() == type) {
				return v;
			}
		}
		return null;
	}
	
	public Value addValue(CombatAttributeType type, int delta, int value) {
		if (values == null)
			values = new ArrayList<Value>(2);
		Value v = new Value(type, delta, value);
		values.add(v);
		return v;
	}
	
	public Action ref() {
		return ref;
	}
	
//	public void addBuff(CombatBuff buff) {
//		unit.addBuff(buff);
//		if (buffs == null)
//			buffs = new ArrayList<CombatBuff>(1);
//		buffs.add(buff);
//	}
//	
//	public void removeBuff(CombatBuff buff) {
//		buff.uneffect();
//		unit.removeBuff(buff);
//		if (buffs == null)
//			buffs = new ArrayList<CombatBuff>(1);
//		buffs.add(buff);
//	}

	//---getters---
	public long getUnitId() {
		return unit.getId();
	}

	public byte getResult() {
		return result;
	}

	public int getHpDelta() {
		Value v = getValue(CombatAttributeType.HP);
		return v != null ? v.delta : 0;
	}

	public int getMpDelta() {
		Value v = getValue(CombatAttributeType.MP);
		return v != null ? v.delta : 0;
	}
	
	public int getHp() {
		Value v = getValue(CombatAttributeType.HP);
		return (int) (v != null ? v.getValue() : unit.getHp());
	}
	
	public int getMp() {
		Value v = getValue(CombatAttributeType.MP);
		return (int) (v != null ? v.getValue() : unit.getMp());
	}

//	public List<CombatBuff> getBuffs() {
//		return buffs != null ? buffs : Collections.emptyList();
//	}
	//---getters---
}
